package fabrica;

/**
 *
 * @author Heliokann
 */
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
//import java.util.WeakHashMap;
import java.util.HashMap;

public class FabricaComCache<T> {
    //Instancia do Factory
    private static FabricaComCache instance;
    //Objeto Map(Genérico) usado como Cache
    private static final Map<Class, Object> cache;

    static {
    //Cria o Cache Anexando-a a classe
        cache = new HashMap<Class, Object>();
        instance = new FabricaComCache();
    }
    //Implementada como Singleton(Padrão GoF)
    private FabricaComCache() {
    }
    //Cria uma Instância Única
    public static final FabricaComCache getInstance() {
        if (instance == null) {
            instance = new FabricaComCache();
        }
        return instance;
    }

    //Método que busca uma Classe pelo Nome
    private Class find(String name) throws Throwable {
        //Busca a Classe
        Class c = Class.forName(name);
        //Não pode ser uma Interface
        if (c.isInterface()) {
            throw new Exception(
                    "Não Suporta Interface Injection");
        }
//        int modificadores = c.getModifiers();
//        if(modificadores == 1024 || modificadores == 1025){
////            Enhancer enhancer = new Enhancer();
////            enhancer.setSuperclass(DaoImpl.class);
////            enhancer.setCallback(new DaoImpl());
//        }
        
        return c;
    }
    //Método que cria a instância de uma classe
    public T getObj(String classe) throws Throwable {
        //A classe é a chave de busca no Map
        Class key = find(classe);
        //Busca se a classe já foi criada
        T retorno = (T) cache.get(key);
        //Testa se o objeto não foi criado
        if (retorno == null) {
            //Log da Criação
//            System.out.println("Criando o Objeto " +key.getName());
            //Cria o objeto
            retorno = (T) key.newInstance();
//            System.out.println("Criou o Objeto " +key.getName());
            //Adiciona ao cache
            cache.put(key, retorno);
            List l = new ArrayList();
        }
        return retorno;
    }
    
    public static <T> T getObj(Class classe) throws Throwable {
        //A classe é a chave de busca no Map
        Class key = classe;
        //Busca se a classe já foi criada
        Object retorno = cache.get(key);
        //Testa se o objeto não foi criado
        if (retorno == null) {
            //Log da Criação
//            System.out.println("Criou o Objeto " +
//                    key.getName());
            //Cria o objeto
            retorno = key.newInstance();
            //Adiciona ao cache
            cache.put(key, retorno);
        }
        return (T)retorno;
    }
    
    
}
